﻿Imports System.Net.FtpClient
Imports System.Threading

Public Class frm_main

    Private Const SPLITTER_DISTANCE As Integer = 72
    Private Shared _settings As New Settings
    Private Shared _ui_context As Tasks.TaskScheduler
    Private Shared _log As NLog.Logger = NLog.LogManager.GetLogger("Main")

    Private _ftp_client As New FtpClient
    Private _reset_event As New ManualResetEvent(False)
    Private _tools As New SFDL.Core.Tools
    Private _connection2modify As SavedFTPConnection
    Private _active_ftp_connection_info As SFDL.File.ConnectionInfo
    Private _package_counter As Integer = 0

    Public Event AddFTPListItems(ByVal sender As Object, ByVal _ftp_items As Object())

    Protected Friend ReadOnly Property GetRootUIContext As Tasks.TaskScheduler
        Get
            Return _ui_context
        End Get
    End Property

    Public WriteOnly Property SetSettings As Settings
        Set(value As Settings)
            _settings = value
        End Set
    End Property

    Public ReadOnly Property GetSettings As Settings
        Get
            Return _settings
        End Get
    End Property

    Public ReadOnly Property GetFTPClient
        Get
            Return _ftp_client
        End Get
    End Property

    Sub RefreshWorkdingDir()

        Try

            _ftp_client.SetWorkingDirectory(txt_current_path.Text)

            _ftp_client.BeginGetListing("", _active_ftp_connection_info.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

            OLV_FTP_Items.Enabled = False

            _log.Info("Aktualisiere Verzeichnis...Bitte Warten")

        Catch ex As Exception

        End Try

    End Sub

    Sub ReadSavedFTPConnections()

        OLV_Saved_FTP_Connections.ClearObjects()

        For Each _saved_connection_file In IO.Directory.GetFiles(IO.Path.Combine(Application.StartupPath, "SavedFTPConnections"), "*.xml")

            Try

                Dim _saved_connection As New SavedFTPConnection

                _saved_connection = _tools.XMLDeSerialize(_saved_connection, _saved_connection_file)
                _saved_connection.FileName = _saved_connection_file

                OLV_Saved_FTP_Connections.AddObject(_saved_connection)

            Catch ex As Exception

            End Try

        Next

    End Sub

    Sub Disconnect(Optional ByVal _new_connection As Boolean = True, Optional ByVal _disconnect_connection As Boolean = True)

        If Not IsNothing(_ftp_client) Then

            Try

                If _ftp_client.IsConnected And _disconnect_connection = True Then
                    _ftp_client.Disconnect()
                End If

                OLV_FTP_Items.ClearObjects()
                txt_current_path.Clear()
                OLV_SFDL.ClearObjects()
                _package_counter = 0

                If _new_connection = True Then
                    ResetFTPConnectionOptions()
                End If

            Catch ex As Exception

            End Try

        End If

    End Sub

    Public Sub ConnectCallback(ByVal ar As IAsyncResult)

        Dim _ftp_client As New FtpClient

        Try

            If IsNothing(ar.AsyncState) Then
                Throw New InvalidOperationException("The FtpControlConnection object is null!")
            End If

            _ftp_client = TryCast(ar.AsyncState, FtpClient)

            _ftp_client.EndConnect(ar)

        Catch ex As Exception

            MessageBox.Show("Verbindung zum FTP-Server konnte hergestellt werden." & vbNewLine & "Fehlermeldung: " & ex.Message, "Verbindungsaufbau fehlgeschlagen!", MessageBoxButtons.OK, MessageBoxIcon.Error)

        Finally
            _reset_event.Set()
        End Try

    End Sub

    Public Sub GetListingCallback(ByVal ar As IAsyncResult)

        Dim _ftp_client As New FtpClient
        Dim _list_ftp_item() As FtpListItem

        Try

            If IsNothing(ar.AsyncState) Then
                Throw New InvalidOperationException("The FtpControlConnection object is null!")
            End If

            _log.Info("Lese Verzeichnisse und Dateien ein (LIST)...")

            _ftp_client = TryCast(ar.AsyncState, FtpClient)

            _list_ftp_item = _ftp_client.EndGetListing(ar)

            RaiseEvent AddFTPListItems(Me, _list_ftp_item)

            _log.Info("LIST erfolgreich!")

        Catch ex As Exception
            MessageBox.Show("LIST Befehl fehlgeschlagen!." & vbNewLine & "Fehlermeldung: " & ex.Message, "LIST fehlgeschlagen!", MessageBoxButtons.OK, MessageBoxIcon.Error)
            _log.Error(ex, ex.Message)
        End Try

    End Sub

    Private Sub AdvancedSettingsExpander_ExpandCollapse(sender As Object, e As MakarovDev.ExpandCollapsePanel.ExpandCollapseEventArgs) Handles AdvancedSettingsExpander.ExpandCollapse

        If e.IsExpanded = True Then
            SplitContainer_Main.SplitterDistance = SPLITTER_DISTANCE + AdvancedSettingsExpander.ExpandedHeight
        Else
            SplitContainer_Main.SplitterDistance = SPLITTER_DISTANCE
        End If

    End Sub

    Private Sub frm_main_Load(sender As Object, e As EventArgs) Handles MyBase.Load


        _settings = New Settings

        If IO.File.Exists("settings.xml") = True Then
            _settings = _tools.XMLDeSerialize(_settings, "settings.xml")
        End If

        _ui_context = Tasks.TaskScheduler.FromCurrentSynchronizationContext 'Für UI Zugriff

        If My.Settings.UserWindowSize.IsEmpty = False Then
            Me.Size = My.Settings.UserWindowSize
        End If

        Me.WindowState = My.Settings.UserWindowsState

        AdvancedSettingsExpander.IsExpanded = False

        comB_DataConnectionMode.SelectedIndex = 0
        ComB_Encoding.SelectedIndex = 0
        ComB_Encryption.SelectedIndex = 0
        ComB_LIST.SelectedIndex = 3

        olv_filename.ImageGetter = New BrightIdeasSoftware.ImageGetterDelegate(AddressOf ImageUpdateEventImageGetter)

        AddHandler Me.AddFTPListItems, AddressOf AddFTPListEvent

        If IO.Directory.Exists(IO.Path.Combine(Application.StartupPath, "SavedFTPConnections")) = False Then
            IO.Directory.CreateDirectory(IO.Path.Combine(Application.StartupPath, "SavedFTPConnections"))
        End If

        ReadSavedFTPConnections()

    End Sub

    Private Sub SplitButton1_Click(sender As Object, e As EventArgs) Handles SplitButton1.Click
        VerbindenToolStripMenuItem.PerformClick()
    End Sub

    Private Sub VerbindenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles VerbindenToolStripMenuItem.Click

        Dim _ftp_connection_options As New SFDL.File.ConnectionInfo

        'Wenn Alte Verbindung vorhanden diese zuerst trennen
        _log.Info("Trenne evtl. vorhandene FTP Verbindung...")
        Disconnect(False)
        _log.Info("OK - Verbindung getrennt")

        Try

            _ftp_client = New FtpClient

            _reset_event.Reset()

            If txt_host.Text.ToLower.StartsWith("ftp://") Then
                _ftp_connection_options = ParseFTPConnectionString(txt_host.Text)
            Else

                If String.IsNullOrWhiteSpace(txt_host.Text) = True Then
                    'Noch versuchen etwas aus der Zwischenablage auszulesen

                    If My.Computer.Clipboard.ContainsText = False Then
                        Throw New Exception("Du musst eine Hostadresse angeben oder einen gültigen FTP Connection String in der Zwischenablage haben!")
                    End If

                    If String.IsNullOrWhiteSpace(My.Computer.Clipboard.GetText) = True Or My.Computer.Clipboard.GetText.StartsWith("ftp://") = False Then
                        Throw New Exception("Keinen gültigen FTP Connection String der Zwischenablage gefunden!")
                    End If

                    _ftp_connection_options = ParseFTPConnectionString(My.Computer.Clipboard.GetText)
                Else
                    _ftp_connection_options = GetFTPConnectionOptions()
                End If

            End If

            _active_ftp_connection_info = _ftp_connection_options

            _ftp_client = SetupFTPConnection(_ftp_connection_options)

            _ftp_client.InternetProtocolVersions = FtpIpVersion.IPv4

            AddHandler _ftp_client.ValidateCertificate, AddressOf SSLValidateCertificateEvent

            LockConnectionBar()

            _log.Info("Baue Verbindung zum FTP Server auf...")

            _ftp_client.BeginConnect(New AsyncCallback(AddressOf ConnectCallback), _ftp_client)

            _reset_event.WaitOne()

            If Not _ftp_client.IsConnected Then
                Throw New Exception("Verbindung fehlgeschlagen!")
            End If

            _log.Info("Verbindung hergestellt!")

            _reset_event.Reset()

            Try
                _ftp_client.SetWorkingDirectory(_ftp_connection_options.DefaultPath)
            Catch ex As Exception
                _ftp_client.SetWorkingDirectory(System.Net.FtpClient.FtpExtensions.GetFtpPath("\"))
            End Try

            _ftp_client.BeginGetListing(_ftp_client.GetWorkingDirectory, _ftp_connection_options.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

            txt_current_path.Text = _ftp_client.GetWorkingDirectory

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
            _log.Error(ex, ex.Message)
        Finally
            UnLockConnectionBar()
        End Try

    End Sub

    Private Sub VerbindenSpeichernToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles VerbindenSpeichernToolStripMenuItem.Click

        Dim _name As String = String.Empty
        Dim _connection As New SavedFTPConnection
        Dim _ftp_connection_options As New SFDL.File.ConnectionInfo

        'Wenn Alte Verbindung vorhanden diese zuerst trennen
        _log.Info("Trenne evtl. vorhandene FTP Verbindung...")
        Disconnect(False)
        _log.Info("OK - Verbindung getrennt")

        Try

            _name = InputBox("Bitte Verbindungsname eingeben: ", "Verbindungsname", "NeueVerbindung")

            If Not String.IsNullOrWhiteSpace(_name) Then
                _connection.ConnectionName = _name
            End If

            If txt_host.Text.ToLower.StartsWith("ftp://") Then
                _ftp_connection_options = ParseFTPConnectionString(txt_host.Text)
            Else

                If String.IsNullOrWhiteSpace(txt_host.Text) = True Then
                    'Noch versuchen etwas aus der Zwischenablage auszulesen

                    If My.Computer.Clipboard.ContainsText = False Then
                        Throw New Exception("Du musst eine Hostadresse angeben oder einen gültigen FTP Connection String in der Zwischenablage haben!")
                    End If

                    If String.IsNullOrWhiteSpace(My.Computer.Clipboard.GetText) = True Or My.Computer.Clipboard.GetText.StartsWith("ftp://") = False Then
                        Throw New Exception("Keinen gültigen FTP Connection String der Zwischenablage gefunden!")
                    End If

                    _ftp_connection_options = ParseFTPConnectionString(My.Computer.Clipboard.GetText)

                Else
                    _ftp_connection_options = GetFTPConnectionOptions()
                End If

            End If

            _connection.FTPConnectionOption = _ftp_connection_options

            _tools.XMLSerialize(_connection, IO.Path.Combine(Application.StartupPath, "SavedFTPConnections\" & Guid.NewGuid.ToString & ".xml"))

            MessageBox.Show("Verbindung erfolgreich gespeichert!", "Verbindung speichern", MessageBoxButtons.OK, MessageBoxIcon.Information)

            ReadSavedFTPConnections()

            _active_ftp_connection_info = _ftp_connection_options

            _ftp_client = SetupFTPConnection(_ftp_connection_options)

            AddHandler _ftp_client.ValidateCertificate, AddressOf SSLValidateCertificateEvent

            LockConnectionBar()

            _log.Info("Baue Verbindung zum FTP Server auf...")

            _ftp_client.BeginConnect(New AsyncCallback(AddressOf ConnectCallback), _ftp_client)

            _reset_event.WaitOne()

            If Not _ftp_client.IsConnected Then
                Throw New Exception("Verbindung fehlgeschlagen!")
            End If

            _log.Info("Verbindung hergestellt!")

            _reset_event.Reset()

            Try
                _ftp_client.SetWorkingDirectory(_ftp_connection_options.DefaultPath)
            Catch ex As Exception
                _ftp_client.SetWorkingDirectory(System.Net.FtpClient.FtpExtensions.GetFtpPath("\"))
            End Try

            _ftp_client.BeginGetListing(_ftp_client.GetWorkingDirectory, _ftp_connection_options.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

            txt_current_path.Text = _ftp_client.GetWorkingDirectory

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
            _log.Error(ex, ex.Message)
        Finally
            UnLockConnectionBar()
        End Try

    End Sub

    Private Sub AddFTPListEvent(ByVal _sender As Object, _ftp_items As Object())

        If OLV_FTP_Items.InvokeRequired Then
            OLV_FTP_Items.Invoke(Sub() AddFTPListEvent(Me, _ftp_items))

        Else

            Try

                OLV_FTP_Items.ClearObjects()

                OLV_FTP_Items.AddObjects(_ftp_items)

                OLV_FTP_Items.RefreshObjects(_ftp_items)

                'Unlock
                OLV_FTP_Items.Enabled = True
                txt_current_path.Text = _ftp_client.GetWorkingDirectory

            Catch ex As Exception

            End Try

        End If

    End Sub

    Private Function ImageUpdateEventImageGetter(ByVal _row_object As Object) As Object

        Dim _item As FtpListItem

        Dim _rt As New Object

        Try

            _item = DirectCast(_row_object, FtpListItem)

            Select Case _item.Type

                Case FtpFileSystemObjectType.Directory

                    _rt = 0

                Case FtpFileSystemObjectType.File

                    _rt = 1

                Case Else

                    _rt = Nothing

            End Select

        Catch ex As Exception

        End Try

        Return _rt

    End Function

    Private Sub cmd_dir_up_Click(sender As Object, e As EventArgs) Handles cmd_dir_up.Click

        Dim _ftp_response As FtpReply

        If _ftp_client.IsConnected = True Then

            _ftp_client.SetWorkingDirectory(txt_current_path.Text)

            _ftp_response = _ftp_client.Execute("CWD ..")

            If _ftp_response.Success = False Then
                MessageBox.Show("Verzeichnis konnte nicht gewechselt werden!" & vbNewLine & "Fehlermeldung: " & _ftp_response.ErrorMessage & "(CODE: " & _ftp_response.Code & ")", "Verzeichnis konnte nicht gewechselt werden!", MessageBoxButtons.OK, MessageBoxIcon.Error)
                _log.Error("Verzeichnis konnte nicht gewechselt werden!" & vbNewLine & "Fehlermeldung: " & _ftp_response.ErrorMessage & "(CODE: " & _ftp_response.Code & ")")
            End If

            _ftp_client.BeginGetListing("", _active_ftp_connection_info.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

        End If

    End Sub

    Private Sub txt_current_path_KeyDown(sender As Object, e As KeyEventArgs) Handles txt_current_path.KeyDown

        If e.KeyData = Keys.Return Or e.KeyData = Keys.Enter Then

            Dim _ftp_response As FtpReply

            If _ftp_client.IsConnected = True Then

                _ftp_response = _ftp_client.Execute(String.Format("CWD {0}", txt_current_path.Text))

                If _ftp_response.Success = False Then
                    MessageBox.Show("Verzeichnis konnte nicht gewechselt werden!" & vbNewLine & "Fehlermeldung: " & _ftp_response.ErrorMessage & "(CODE: " & _ftp_response.Code & ")", "Verzeichnis konnte nicht gewechselt werden!", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    _log.Error("Verzeichnis konnte nicht gewechselt werden!" & vbNewLine & "Fehlermeldung: " & _ftp_response.ErrorMessage & "(CODE: " & _ftp_response.Code & ")")
                End If

                _ftp_client.BeginGetListing(txt_current_path.Text, _active_ftp_connection_info.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

                If Not txt_current_path.Text.ToLower.Equals(_ftp_client.GetWorkingDirectory.ToLower) Then
                    MessageBox.Show("Achtung! - Der FTP gibt als Aktuelles Verzeichnis einen anderen Pfad zurück als den in den du gerade gewechselt hast." & vbNewLine & "Dadurch kann es sein das die SFDL mit SFDL.NET Loader nicht korrekt funktioniert." & vbNewLine & "Evtl. musst die Pfade manuell in der SFDL anpassen.", "Achtung", MessageBoxButtons.OK, MessageBoxIcon.Warning)
                End If

            End If

        End If

    End Sub

    Private Sub OrdnerErstellenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OrdnerErstellenToolStripMenuItem.Click

        Dim _folder_name As String = String.Empty

        _folder_name = InputBox("Bitte Ordnernamen eingeben:", "Neuer Ordner", "New Folder")

        If Not String.IsNullOrWhiteSpace(_folder_name) Then

            If _ftp_client.IsConnected Then

                Try

                    _ftp_client.CreateDirectory(System.Net.FtpClient.FtpExtensions.GetFtpPath(IO.Path.Combine(txt_current_path.Text, _folder_name)))

                Catch ex As Exception
                    MessageBox.Show("Ordner konnte nicht erstellt werden!" & vbNewLine & "Fehlermeldung: " & ex.Message, "Ordner erstellen fehlgeschlagen!", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Finally
                    RefreshWorkdingDir()
                End Try

            End If

        End If

    End Sub

    Private Sub OLV_FTP_Items_DoubleClick(sender As Object, e As EventArgs) Handles OLV_FTP_Items.DoubleClick

        If Not OLV_FTP_Items.SelectedObjects.Count = 0 Then

            Dim _item As FtpListItem

            Try

                If _ftp_client.IsConnected Then

                    _item = TryCast(OLV_FTP_Items.SelectedObject, FtpListItem)

                    If _item.Type = FtpFileSystemObjectType.Directory Then

                        _ftp_client.SetWorkingDirectory(_item.FullName)

                        _ftp_client.BeginGetListing("", _active_ftp_connection_info.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

                        OLV_FTP_Items.Enabled = False

                        _log.Info("Hole LIST...Bitte Warten...")

                    End If

                End If

            Catch ex As Exception
                MessageBox.Show("Verzeichnis konnte nicht gewechselt werden!" & vbNewLine & "Fehlermeldung: " & ex.Message, "Verzeichnis konnte nicht gewechselt werden!", MessageBoxButtons.OK, MessageBoxIcon.Error)
                _log.Error(ex, ex.Message)
                OLV_FTP_Items.Enabled = True
            End Try

        End If

    End Sub

    Private Sub cmd_disconnect_Click(sender As Object, e As EventArgs) Handles cmd_disconnect.Click
        Disconnect()
    End Sub

    Private Sub BeendenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BeendenToolStripMenuItem.Click
        Application.Exit()
    End Sub

    Private Sub frm_main_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing

        Try

            Disconnect()
            My.Settings.UserWindowSize = Me.Size
            My.Settings.UserWindowsState = Me.WindowState
            My.Settings.Save()

        Catch ex As Exception
        End Try

    End Sub

    Private Sub EinstellungenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EinstellungenToolStripMenuItem.Click
        frm_settings.ShowDialog()
    End Sub

    Private Sub LöschenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles LöschenToolStripMenuItem.Click

        Try

            If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then

                If MessageBox.Show("Makierte Verbindung(en) löschen?", "Verbindung(en) löschen", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then

                    For Each _saved_connection As SavedFTPConnection In OLV_Saved_FTP_Connections.SelectedObjects

                        If IO.File.Exists(_saved_connection.FileName) Then
                            IO.File.Delete(_saved_connection.FileName)
                        End If

                    Next

                End If

            End If

        Catch ex As Exception
            MessageBox.Show("Fehler beim löschen der Verbindung(en)!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            ReadSavedFTPConnections()
        End Try

    End Sub

    Private Sub VerbindungHerstellenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles VerbindungHerstellenToolStripMenuItem.Click, OLV_Saved_FTP_Connections.DoubleClick

        Try

            If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then

                Dim _saved_connection_item As SavedFTPConnection = OLV_Saved_FTP_Connections.SelectedObjects(0)
                Dim _ftp_connection_options As SFDL.File.ConnectionInfo = _saved_connection_item.FTPConnectionOption

                Disconnect(False, False)

                _active_ftp_connection_info = _ftp_connection_options

                _ftp_client = SetupFTPConnection(_ftp_connection_options)

                AddHandler _ftp_client.ValidateCertificate, AddressOf SSLValidateCertificateEvent

                LockConnectionBar()

                _log.Info("Baue Verbindung zum FTP Server auf...")

                _ftp_client.BeginConnect(New AsyncCallback(AddressOf ConnectCallback), _ftp_client)

                _reset_event.WaitOne()

                If Not _ftp_client.IsConnected Then
                    Throw New Exception("Verbindung fehlgeschlagen!")
                End If

                _log.Info("Verbindung hergestellt!")

                _reset_event.Reset()

                Try
                    _ftp_client.SetWorkingDirectory(_ftp_connection_options.DefaultPath)
                Catch ex As Exception
                    _ftp_client.SetWorkingDirectory(System.Net.FtpClient.FtpExtensions.GetFtpPath("\"))
                End Try

                _ftp_client.BeginGetListing(_ftp_client.GetWorkingDirectory, _ftp_connection_options.ListMethod, New AsyncCallback(AddressOf GetListingCallback), _ftp_client)

                txt_current_path.Text = _ftp_client.GetWorkingDirectory

            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
            _log.Error(ex, ex.Message)
        Finally
            UnLockConnectionBar()
        End Try

    End Sub

    Private Sub UmbenennenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles UmbenennenToolStripMenuItem.Click

        If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then
            OLV_Saved_FTP_Connections.StartCellEdit(OLV_Saved_FTP_Connections.ModelToItem(OLV_Saved_FTP_Connections.SelectedObjects(0)), 0)
        End If

    End Sub

    Private Sub ServerIDSetztenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ServerIDSetztenToolStripMenuItem.Click
        If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then

            Dim _item As New SavedFTPConnection

            _item = OLV_Saved_FTP_Connections.SelectedObjects(0)

            _item.ServerID = "Neue ServerID"

            OLV_Saved_FTP_Connections.RefreshObject(_item)

            OLV_Saved_FTP_Connections.StartCellEdit(OLV_Saved_FTP_Connections.ModelToItem(OLV_Saved_FTP_Connections.SelectedObjects(0)), 1)

        End If
    End Sub

    Private Sub OLV_Saved_FTP_Connections_CellEditFinishing(sender As Object, e As BrightIdeasSoftware.CellEditEventArgs) Handles OLV_Saved_FTP_Connections.CellEditFinishing

        Dim _saved_connection_item As New SavedFTPConnection

        Try

            _saved_connection_item = TryCast(e.RowObject, SavedFTPConnection)

            Select Case e.SubItemIndex

                Case 0 'Name

                    If String.IsNullOrWhiteSpace(e.NewValue) Then
                        Throw New Exception("Name der Verbindung darf nicht leer sein!")
                    End If

                    _saved_connection_item.ConnectionName = e.NewValue

                Case 1 'ServerID

                    _saved_connection_item.ServerID = e.NewValue

                Case Else

                    'Do nothing

            End Select

            If IO.File.Exists(_saved_connection_item.FileName) Then
                IO.File.Delete(_saved_connection_item.FileName)
            End If

            _tools.XMLSerialize(_saved_connection_item, IO.Path.Combine(Application.StartupPath, "SavedFTPConnections\" & Guid.NewGuid.ToString & ".xml"))

        Catch ex As Exception
            MessageBox.Show("Bearbeiten der Verbindung fehlgeschlagen." & vbNewLine & "Fehlermeldung: " & ex.Message, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            ReadSavedFTPConnections()
        End Try

    End Sub

    Private Sub BearbeitenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BearbeitenToolStripMenuItem.Click

        If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then

            Dim _saved_connection As New SavedFTPConnection

            _saved_connection = OLV_Saved_FTP_Connections.SelectedObjects(0)

            _connection2modify = _saved_connection

            ModifyConnection(_saved_connection.FTPConnectionOption)

        End If

    End Sub

    Private Sub BenutzerdefinierteInfoÄndernToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BenutzerdefinierteInfoÄndernToolStripMenuItem.Click

        Dim _saved_connection_item As SavedFTPConnection

        Try

            If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then

                _saved_connection_item = OLV_Saved_FTP_Connections.SelectedObjects(0)

                frm_change_ftp_cutom_text.SaveFTPConnectionItem = _saved_connection_item

                frm_change_ftp_cutom_text.ShowDialog()

                _saved_connection_item = frm_change_ftp_cutom_text.SaveFTPConnectionItem

                If IO.File.Exists(_saved_connection_item.FileName) Then
                    IO.File.Delete(_saved_connection_item.FileName)
                End If

                _tools.XMLSerialize(_saved_connection_item, IO.Path.Combine(Application.StartupPath, "SavedFTPConnections\" & Guid.NewGuid.ToString & ".xml"))

            End If

        Catch ex As Exception
            MessageBox.Show("Fehler beim bearbeiten der FTP Verbindung.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            ReadSavedFTPConnections()
        End Try

    End Sub

    Private Sub OLV_Saved_FTP_Connections_SelectionChanged(sender As Object, e As EventArgs) Handles OLV_Saved_FTP_Connections.SelectionChanged

        If Not OLV_Saved_FTP_Connections.SelectedObjects.Count = 0 Then

            Dim _saved_connection_item As SavedFTPConnection

            _saved_connection_item = OLV_Saved_FTP_Connections.SelectedObjects(0)

            RTB_FTP_Custom_Text.Clear()
            RTB_FTP_Custom_Text.Text = _saved_connection_item.CustomInfo

        End If

    End Sub

    Private Sub txt_connection_search_KeyDown(sender As Object, e As KeyEventArgs) Handles txt_connection_search.KeyDown

        If e.KeyCode = Keys.Return Or e.KeyCode = Keys.Enter Then

            Dim _filter As BrightIdeasSoftware.TextMatchFilter

            _filter = BrightIdeasSoftware.TextMatchFilter.Contains(OLV_Saved_FTP_Connections, txt_connection_search.Text)
            OLV_Saved_FTP_Connections.ModelFilter = _filter
            OLV_Saved_FTP_Connections.DefaultRenderer = New BrightIdeasSoftware.HighlightTextRenderer(_filter)

        End If

    End Sub

    Private Sub cmd_save_changes_Click(sender As Object, e As EventArgs) Handles cmd_save_changes.Click

        Try

            Dim _modified_connection As New SavedFTPConnection

            _modified_connection = _connection2modify

            _modified_connection.FTPConnectionOption = GetFTPConnectionOptions()

            If IO.File.Exists(_modified_connection.FileName) Then
                IO.File.Delete(_modified_connection.FileName)
            End If

            _tools.XMLSerialize(_modified_connection, IO.Path.Combine(Application.StartupPath, "SavedFTPConnections\" & Guid.NewGuid.ToString & ".xml"))

            MessageBox.Show("FTP Verbindung erfolgreich geändert!", "FTP Verbindung", MessageBoxButtons.OK, MessageBoxIcon.Information)

        Catch ex As Exception
            MessageBox.Show("Fehler beim bearbeiten der FTP Verbindung!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            cmd_save_changes.Visible = False
            cmd_save_changes.Enabled = False
            AdvancedSettingsExpander.IsExpanded = False
            ReadSavedFTPConnections()
        End Try

    End Sub

    Private Sub ZuSFDLContainerHinzufügenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ZuSFDLContainerHinzufügenToolStripMenuItem.Click

        Dim _package_name As String = String.Empty
        Dim _selected_objects_file As New List(Of FtpListItem)
        Dim _selected_objects_dir As New List(Of FtpListItem)
        Dim _selected_objects As New List(Of FtpListItem)

        OLV_FTP_Items.Enabled = False
        OLV_SFDL.Enabled = False

        _log.Info("Hole Ermittle Dateien und Unterordner - Das kann je nach größe etwas dauern...")

        For Each _object As FtpListItem In OLV_FTP_Items.SelectedObjects

            Select Case _object.Type

                Case FtpFileSystemObjectType.Directory

                    _selected_objects_dir.Add(_object)

                Case FtpFileSystemObjectType.File

                    _selected_objects_file.Add(_object)

            End Select

        Next

        If Not _selected_objects_file.Count = 0 Then

            Dim _sfdl_file_items As New List(Of OLV_SFDL_Item)

            _package_counter += 1
            _package_name = String.Format("Package {0}", _package_counter)

            System.Threading.Tasks.Task.Factory.StartNew(Sub()

                                                             System.Threading.Tasks.Parallel.ForEach(_selected_objects_file, Sub(_selected_ftp_item As FtpListItem)

                                                                                                                                 Dim _sfdl_item As New OLV_SFDL_Item

                                                                                                                                 If MatchExcludedFileList(_selected_ftp_item.Name) = False Then

                                                                                                                                     _sfdl_item.FileName = _selected_ftp_item.Name
                                                                                                                                     _sfdl_item.FileFullPath = _selected_ftp_item.FullName
                                                                                                                                     _sfdl_item.FileSize = _selected_ftp_item.Size
                                                                                                                                     _sfdl_item.PackageName = _package_name
                                                                                                                                     _sfdl_item.DirectoryPath = _selected_ftp_item.FullName.Replace(_selected_ftp_item.Name, "")
                                                                                                                                     _sfdl_item.DirectoryRoot = _selected_ftp_item.FullName.Replace(_selected_ftp_item.Name, "")
                                                                                                                                     _sfdl_item.FileHash = String.Empty
                                                                                                                                     _sfdl_item.FileHashType = File.FileInfo.HashType.None

                                                                                                                                     _sfdl_file_items.Add(_sfdl_item)

                                                                                                                                 End If

                                                                                                                             End Sub)

                                                         End Sub).ContinueWith(Sub()
                                                                                   OLV_SFDL.AddObjects(_sfdl_file_items)
                                                                               End Sub, New CancellationToken, Tasks.TaskContinuationOptions.AttachedToParent, _ui_context)

        End If

        If Not _selected_objects_dir.Count = 0 Then

            Dim _sfdl_item_list As New List(Of OLV_SFDL_Item)

            System.Threading.Tasks.Task.Factory.StartNew(Sub()

                                                             For Each _dirobject As FtpListItem In _selected_objects_dir

                                                                 Dim _bgw_args As New BGW_DirListDeepArgs

                                                                 If _settings.UseFolderNameAsPackagename = True Then
                                                                     _bgw_args.PackageName = _dirobject.Name
                                                                 Else
                                                                     _package_counter += 1
                                                                     _package_name = String.Format("Package {0}", _package_counter)
                                                                     _bgw_args.PackageName = _package_name
                                                                 End If

                                                                 _bgw_args.Path = _dirobject.FullName

                                                                 _sfdl_item_list.AddRange(DirListDeep(_bgw_args.Path, _bgw_args.PackageName, _ftp_client, _active_ftp_connection_info.ListMethod, _bgw_args.Path))

                                                             Next

                                                         End Sub).ContinueWith(Sub()
                                                                                   OLV_SFDL.AddObjects(_sfdl_item_list)

                                                                                   OLV_FTP_Items.Enabled = True
                                                                                   OLV_SFDL.Enabled = True

                                                                               End Sub, New CancellationToken, Tasks.TaskContinuationOptions.AttachedToParent, _ui_context)

        Else
            OLV_FTP_Items.Enabled = True
            OLV_SFDL.Enabled = True
        End If

    End Sub

    Private Sub SSLValidateCertificateEvent(control As FtpClient, e As FtpSslValidationEventArgs)
        e.Accept = True
    End Sub

    Private Sub OLV_SFDL_AboutToCreateGroups(sender As Object, e As BrightIdeasSoftware.CreateGroupsEventArgs) Handles OLV_SFDL.AboutToCreateGroups

        For Each _group In e.Groups
            _group.Task = "Paket Umbennnen"
        Next

    End Sub

    Private Sub OLV_SFDL_GroupTaskClicked(sender As Object, e As BrightIdeasSoftware.GroupTaskClickedEventArgs) Handles OLV_SFDL.GroupTaskClicked

        Dim _new_name As String

        _new_name = InputBox("Bitte gib einen neuen Paketnamen ein:", "Packet Name")

        For Each _item In e.Group.Items

            Dim _olv_item As OLV_SFDL_Item

            _olv_item = OLV_SFDL.Objects(_item.Index)
            _olv_item.PackageName = _new_name

        Next

        OLV_SFDL.RebuildColumns()

    End Sub

    Private Sub EntfernenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EntfernenToolStripMenuItem.Click
        OLV_SFDL.RemoveObjects(OLV_SFDL.SelectedObjects)
    End Sub

    Private Sub SFDLErstellenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SFDLErstellenToolStripMenuItem.Click, SFDLErstellenToolStripMenuItem1.Click

        Try

            Dim _new_list As New List(Of OLV_SFDL_Item)

            If OLV_SFDL.GetItemCount = 0 Then
                Throw New Exception("Keine Datein zum erstellen einer SFDL vorhanden!")
            End If

            frm_create_sfdl.FTPConnectionInfo = _active_ftp_connection_info

            For Each _item As OLV_SFDL_Item In OLV_SFDL.Objects
                _new_list.Add(_item)
            Next

            frm_create_sfdl.SFDLFiles = _new_list
            frm_create_sfdl.ShowDialog()

            frm_create_sfdl.Dispose()

            If _settings.ClearSFDLFileQueueAfterCreation = True Then
                OLV_SFDL.ClearObjects()
            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Was vergessen?", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    Private Sub AlsBulkFolderZuSFDLContainerHinzufügenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AlsBulkFolderZuSFDLContainerHinzufügenToolStripMenuItem.Click

        Try

            If Not OLV_FTP_Items.SelectedObjects.Count = 0 Then

                Dim _sel_object As New FtpListItem
                Dim _package_name As String = String.Empty
                Dim _olv_sfdl_item As New OLV_SFDL_Item

                _sel_object = OLV_FTP_Items.SelectedObjects(0)

                If Not _sel_object.Type = FtpFileSystemObjectType.Directory Then
                    Throw New Exception("Als BulkFolder kann nur ein Ordner hinzugefügt werden!")
                End If

                If _settings.UseFolderNameAsPackagename = True Then
                    _package_name = _sel_object.Name
                Else
                    _package_counter += 1
                    _package_name = String.Format("Package {0}", _package_counter)
                End If

                With _olv_sfdl_item

                    .FileFullPath = "BulkFolder " & _sel_object.FullName
                    .DirectoryPath = _sel_object.FullName
                    .PackageName = _package_name
                    .IsBulkFolder = True

                End With

                OLV_SFDL.AddObject(_olv_sfdl_item)

            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Nicht möglich", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
        End Try

    End Sub

    Private Sub AktuellesVerzeichnisAlsBulkFolderHinzufügenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AktuellesVerzeichnisAlsBulkFolderHinzufügenToolStripMenuItem.Click

        Dim _package_name As String = String.Empty
        Dim _olv_sfdl_item As New OLV_SFDL_Item

        _package_counter += 1
        _package_name = String.Format("Package {0}", _package_counter)

        With _olv_sfdl_item

            .FileFullPath = "BulkFolder " & _ftp_client.GetWorkingDirectory
            .DirectoryPath = _ftp_client.GetWorkingDirectory
            .PackageName = _package_name
            .IsBulkFolder = True

        End With

        OLV_SFDL.AddObject(_olv_sfdl_item)

    End Sub

    Private Sub OrdnerLöschenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OrdnerLöschenToolStripMenuItem.Click

        Try

            If Not OLV_FTP_Items.SelectedObjects.Count = 0 Then

                If MessageBox.Show("Alle makrierten Ordner wirklich löschen?", "Ordner löschen", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then

                    For Each _folder As FtpListItem In OLV_FTP_Items.SelectedObjects

                        If _folder.Type = FtpFileSystemObjectType.Directory Then
                            _ftp_client.DeleteDirectory(_folder.FullName)
                        End If

                    Next

                End If

            End If

        Catch ex As Exception
            MessageBox.Show("Ordner konnte nicht gelöscht werden!", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
        Finally
            RefreshWorkdingDir()
        End Try

    End Sub

    Private Sub ToolStripButton1_Click(sender As Object, e As EventArgs) Handles ToolStripButton1.Click
        RefreshWorkdingDir()
    End Sub

    Private Sub QueueLeerenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles QueueLeerenToolStripMenuItem.Click
        _package_counter = 0
        OLV_SFDL.ClearObjects()
    End Sub

    Private Sub OrdnernamenKopierenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OrdnernamenKopierenToolStripMenuItem.Click

        If Not OLV_FTP_Items.SelectedObjects.Count = 0 Then

            Dim _sel_item As FtpListItem

            _sel_item = OLV_FTP_Items.SelectedObjects(0)

            My.Computer.Clipboard.Clear()

            My.Computer.Clipboard.SetText(_sel_item.Name.ToString)

        End If

    End Sub

    Private Sub chk_special_mode_CheckedChanged(sender As Object, e As EventArgs) Handles chk_special_mode.CheckedChanged
        If chk_special_mode.Checked = True Then
            chk_force_single_connection.Checked = True
            chk_force_single_connection.Enabled = False
            comB_DataConnectionMode.SelectedIndex = 4
        Else
            comB_DataConnectionMode.SelectedIndex = 0
            chk_force_single_connection.Checked = False
            chk_force_single_connection.Enabled = True
        End If
    End Sub

    Private Sub TableLayoutPanel3_Paint(sender As Object, e As PaintEventArgs) Handles TableLayoutPanel3.Paint

    End Sub
End Class